package com.haoqizhe.kernel.mybatis.generator.plugins;

import com.haoqizhe.kernel.mybatis.generator.utils.AnnotationEnum;
import com.haoqizhe.kernel.mybatis.generator.utils.StringUtils;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.XmlElement;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
 * 定制mapper生成插件
 *
 * @author haoqizhe.li
 * @date 2018/3/16 15:08
 */
public class MapperPlugin extends PluginAdapter {

    private static final Set<AnnotationEnum> LOMBOK_ENUM = new LinkedHashSet<>();
    private Properties systemPro;
    /**
     * 生成代码作者
     **/
    private String author;
    /**
     * service 继承的父接口
     **/
    private String rootInterface;

    public MapperPlugin() {
        systemPro = System.getProperties();
    }

    public boolean validate(List<String> list) {
        return true;
    }

    /**
     * 获取配置的信息
     *
     * @param properties
     */
    public void setProperties(Properties properties) {
        try {
            super.setProperties(properties);

            author = properties.getProperty("author", systemPro.getProperty("user.name"));
            rootInterface = properties.getProperty("rootInterface");

            if (rootInterface == null || "".equals(rootInterface)) {
                throw new RuntimeException("MapperPlugin插件缺少必须的rootInterface参数值");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 配置Mapper类 继承父类接口 和 添加注解
     *
     * @param interfaze
     * @param introspectedTable
     * @return
     */
    public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
        try {
            if (introspectedTable.getTargetRuntime() == IntrospectedTable.TargetRuntime.MYBATIS3) {
                interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper"));
                interfaze.addAnnotation("@Mapper");
            }

            Object table = introspectedTable.getRemarks() == null || "".equals(introspectedTable.getRemarks()) ?
                    introspectedTable.getFullyQualifiedTable() : introspectedTable.getRemarks();

            interfaze.addJavaDocLine(StringUtils.getComment(table + "接口", author));
            FullyQualifiedJavaType entityType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
            /**
             * 继承父类
             */
            interfaze.addImportedType(new FullyQualifiedJavaType(rootInterface));
            interfaze.addSuperInterface(new FullyQualifiedJavaType(rootInterface + "<" + entityType.getShortName() + ">"));
            interfaze.addImportedType(entityType);
            /**
             * 添加注解
             */
            for (AnnotationEnum lombokEnum : LOMBOK_ENUM) {
                interfaze.addImportedType(new FullyQualifiedJavaType(lombokEnum.importedType));
                interfaze.addAnnotation(lombokEnum.annotation);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Mapper插件生成Mapper类异常:" + e.getMessage());
        }
    }


    public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    public boolean clientInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    public boolean clientSelectAllMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapDeleteByPrimaryKeyElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapInsertElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapInsertSelectiveElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapSelectAllElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapSelectByPrimaryKeyElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapUpdateByPrimaryKeySelectiveElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapUpdateByPrimaryKeyWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean providerGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean providerApplyWhereMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean providerInsertSelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        return false;
    }

    
    public boolean providerUpdateByPrimaryKeySelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        return false;
    }
}
